<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        /** 前置知识： 
         * 可迭代对象、 (iterable) 满足 
         * 可迭代协议、(规则) 知名符号、(对应的属性是一个函数) 迭代器 生成器
         * 说明：数组是满足要求的因为有 [Symbol.iterator] 是ES6底层的东西 才可以解构
         */
        /*  var arr = [a = 1, b = 2]
        var myitem = arr[Symbol.iterator]() //迭代器 是一个对象
        console.log(myitem, 'myitem'); //Array Iterator {}  
        //Array Iterator {} 里面有一个方法 next()每调用一次就会拿到一个值
        console.log(myitem.next(), 'myitem');  
        console.log(myitem.next(), 'myitem');
        console.log(myitem.next(), 'myitem'); //done:true拿完了 */
        /** 但是对象不满足要求需要变成可迭代对象  如何变？ 
         * 什么是解构(本质)？ 原来的解释 把数组的第一项赋值给第一个... 
         * 本质是使用迭代器 xx[Symbol.iterator]调用next().value 给变量赋值 
         * 注意：迭代器解构数组 也可以解构对象...
         */
        //不希望在对象里加这个迭代器 使用原型
        //原型：
        /*   Object.prototype[Symbol.iterator] = function () {
              var arr = Object.values(this)
              const meitem = arr[Symbol.iterator]()
              return meitem
          } */
        // 简写
        // Object.prototype[Symbol.iterator] = function () {
        //     return Object.values(this)[Symbol.iterator]()
        // }
        //生成器
        Object.prototype[Symbol.iterator] = function* () {
            return yield* Object.values(this)
        }
        var [a, b] = {
            a: 10,
            b: 20,
            // [Symbol.iterator]() {
            //     // var arr = [1,2]
            //     var arr = Object.values(this)
            //     const meitem = arr[Symbol.iterator]()
            //     console.log(meitem, 'meitem');
            //     return meitem
            // }
        }
        console.log(a, 'a', b, 'b');

        /* ********************************************************* */
        /** 如何在不改变下面代码的情况下修改obj      --闭包的漏洞--
         * valueOf 会返回对象自身
         */
        var o = (function () {
            var obj = {
                a: 1,
                b: 2
            }
            //方案2
            Object.setPrototypeOf(obj,null)
            return {
                //去获取obj的某个属性 只获取不更改保证obj完整
                get: function (k) {
                //返回的是对象成员 this指向问题 如果是方法就好办了 return obj[k]()
                    // return obj[k]   
                    // if(obj.hasOwnProperty(k)){
                    //     return obj[k] 
                    // }else{
                    //     return undefined
                    // }  
                    return obj[k] 
                }
            }
        })()
        /* ********************************************** */
        //在对象上调用valueOf方法 会报错 this指向问题
        // console.log(o.get('valueOf'()));
        // 利用读取成员触发方法来解决问题 思考 当我们去读取成员 就是函数调用？？？ 
        // 当属性是访问器时
        Object.defineProperty(Object.prototype, 'abc', {
            get() {
                return this //当传递了abc 返回obj对象成员
            }
        })
          console.log(o.get('abc'),'aa');
          var obj2 = o.get('abc')
          obj2.c = 3
          obj2.d = 4
          console.log(o.get('abc'),'88888');
        /** 这严重破坏了数据：
         * 方案1 验证 看一下这个属性是不是本身属性 不能是原型上的 obj.hasOwnProperty 
         * 方案2 把原型设置为 null
         */
    </script>
</body>

</html>